package com.hippo.core.service;

import com.alibaba.fastjson.JSONObject;
import com.hippo.core.dao.DataSourceDao;
import com.hippo.core.util.CommonUtil;
import com.hippo.core.util.DruidConnectionPool;
import com.hippo.core.util.constants.JdbcDriverEnum;
import com.hippo.core.util.sm4.SM4Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: hippo
 */
@Service
@Slf4j
public class DataSourceService {
    @Autowired
    private DataSourceDao dataSourceDao;

    public JSONObject getDataSourceList(JSONObject jsonObject) {
        CommonUtil.fillPageParam(jsonObject);
        int count = dataSourceDao.countDataSource(jsonObject);
        List<JSONObject> list = dataSourceDao.getDataSourceList(jsonObject);
        return CommonUtil.successPage(jsonObject, list, count);
    }

    public JSONObject addDataSource(JSONObject data) {
        return CommonUtil.response(dataSourceDao.addDataSource(data));
    }

    public JSONObject deleteDataSource(String id) {
        return CommonUtil.response(dataSourceDao.deleteDataSource(id));
    }

    public JSONObject updateDataSource(JSONObject data) {
        return CommonUtil.response(dataSourceDao.updateDataSource(data));
    }

    public static HashMap<String, String> getConnInfoByDbType(JSONObject jsonObject) {
        String dbType = jsonObject.getString("dbType");
        String port = jsonObject.getString("port");
        String dbName = jsonObject.getString("dbName");
        String host = jsonObject.getString("host");
        HashMap<String, String> map = new HashMap<String, String>();
        if (dbType.equals("mysql")) {
            map.put("showTableSql", "select table_name from information_schema.tables where table_schema=? and table_type='BASE TABLE';");
            map.put("showColumnSql", "select COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT,IS_NULLABLE,COLUMN_KEY from information_schema.columns where table_name=? and table_schema=? ORDER BY ORDINAL_POSITION");
            map.put("driver", JdbcDriverEnum.MYSQL.driver);
            map.put("url", "jdbc:mysql://" + host + ":" + port + "/" + dbName);
        } else if (dbType.equals("clickhouse")) {
            map.put("showTableSql", "select DISTINCT `table` as TABLE_NAME from  system.columns where database = ?;");
            map.put("showColumnSql", "select distinct name as COLUMN_NAME,type as COLUMN_TYPE,comment as COLUMN_COMMENT from system.columns where table=? and database=?");
            map.put("driver", JdbcDriverEnum.CLICKHOUSE.driver);
            map.put("url", "jdbc:clickhouse://" + host + ":" + port + "/" + dbName);
        }
        map.put("getTableCountSql", "select count(*) from ");
        return map;
    }

    public JSONObject testConnect(JSONObject jsonObject) {
        HashMap<String, String> connInfo = getConnInfoByDbType(jsonObject);
        String msg = "测试链接成功";
        try {
            Class.forName(connInfo.get("driver"));
            Connection connection = DriverManager.getConnection(connInfo.get("url"), jsonObject.getString("username"),
                    SM4Utils.decryptData_CBC(jsonObject.getString("password")));
            return CommonUtil.successJson(msg);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.toString());
            return CommonUtil.errorJson(e.getMessage());
        }
    }

    public JSONObject getConnect(JSONObject jsonObject) {
        JSONObject jsonObject1 = testConnect(jsonObject);
        if (jsonObject1.getString("code").equals("500")) {
            return CommonUtil.errorJson(jsonObject1.getString("msg"));
        }
        HashMap<String, String> connInfoMap = getConnInfoByDbType(jsonObject);
        String[] arr = new String[]{jsonObject.getString("dbName")};
        try {
            List<Map<String, Object>> maps = DruidConnectionPool.executeQuery(connInfoMap.get("driver"), connInfoMap.get("url"),
                    jsonObject.getString("username"),
                    SM4Utils.decryptData_CBC(jsonObject.getString("password")), connInfoMap.get("showTableSql"), arr);
            return CommonUtil.successJson(maps);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.toString());
            return CommonUtil.errorJson(e.getMessage());
        }
    }

    public JSONObject getFieldByTableName(JSONObject jsonObject) {
        HashMap<String, String> connInfoMap = getConnInfoByDbType(jsonObject);
        String[] sql = new String[]{jsonObject.getString("tableName"), jsonObject.getString("dbName")};
        try {
            List<Map<String, Object>> maps = DruidConnectionPool.executeQuery(connInfoMap.get("driver"), connInfoMap.get("url"), jsonObject.getString("username"),
                    SM4Utils.decryptData_CBC(jsonObject.getString("password")), connInfoMap.get("showColumnSql"), sql);
            return CommonUtil.successJson(maps);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonUtil.errorJson(e.getMessage());
        }
    }

    public JSONObject getCountByTableName(JSONObject jsonObject) {
        HashMap<String, String> connInfoMap = getConnInfoByDbType(jsonObject);
        String[] sql = new String[]{""};
        try {
            List<Map<String, Object>> maps = DruidConnectionPool.executeQuery(connInfoMap.get("driver"), connInfoMap.get("url"), jsonObject.getString("username"),
                    SM4Utils.decryptData_CBC(jsonObject.getString("password")),
                    connInfoMap.get("getTableCountSql") + jsonObject.getString("dbName") + "." + jsonObject.getString("tableName"), sql);
            System.out.println(maps);
            return CommonUtil.successJson(maps);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonUtil.errorJson(e.getMessage());
        }
    }
}
